library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity voter is
	port (
	
		-- inputs:
		d_address_in_0 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        d_byteenable_in_0 : in STD_LOGIC_VECTOR (3 DOWNTO 0);
        d_read_in_0 : in STD_LOGIC;
        d_write_in_0 : in STD_LOGIC;
        d_writedata_in_0 : in STD_LOGIC_VECTOR (31 DOWNTO 0);
        i_address_in_0 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        i_read_in_0 : in STD_LOGIC;
			
		d_address_in_1 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        d_byteenable_in_1 : in STD_LOGIC_VECTOR (3 DOWNTO 0);
        d_read_in_1 : in STD_LOGIC;
        d_write_in_1 : in STD_LOGIC;
        d_writedata_in_1 : in STD_LOGIC_VECTOR (31 DOWNTO 0);
        i_address_in_1 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        i_read_in_1 : in STD_LOGIC;
			
		d_address_in_2 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        d_byteenable_in_2 : in STD_LOGIC_VECTOR (3 DOWNTO 0);
        d_read_in_2 : in STD_LOGIC;
        d_write_in_2 : in STD_LOGIC;
        d_writedata_in_2 : in STD_LOGIC_VECTOR (31 DOWNTO 0);
        i_address_in_2 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        i_read_in_2 : in STD_LOGIC;
			
		d_address_in_3 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        d_byteenable_in_3 : in STD_LOGIC_VECTOR (3 DOWNTO 0);
        d_read_in_3 : in STD_LOGIC;
        d_write_in_3 : in STD_LOGIC;
        d_writedata_in_3 : in STD_LOGIC_VECTOR (31 DOWNTO 0);
        i_address_in_3 : in STD_LOGIC_VECTOR (14 DOWNTO 0);
        i_read_in_3 : in STD_LOGIC;
		
		sel0 : in std_logic_vector (1 downto 0);
		sel1 : in std_logic_vector (1 downto 0);
		sel2 : in std_logic_vector (1 downto 0);

		
		-- outputs:
		d_address : OUT STD_LOGIC_VECTOR (14 DOWNTO 0);
        d_byteenable : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);
        d_read : OUT STD_LOGIC;
        d_write : OUT STD_LOGIC;
        d_writedata : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
        i_address : OUT STD_LOGIC_VECTOR (14 DOWNTO 0);
        i_read : OUT STD_LOGIC;
		
		fault_0 : out std_logic;
		fault_1 : out std_logic;
		fault_2 : out std_logic
		
	);
end entity;

architecture behavioral of voter is

signal aux_d_address : STD_LOGIC_VECTOR (14 DOWNTO 0);
signal aux_d_byteenable : STD_LOGIC_VECTOR (3 DOWNTO 0);
signal aux_d_read : STD_LOGIC;
signal aux_d_write : STD_LOGIC;
signal aux_d_writedata : STD_LOGIC_VECTOR (31 DOWNTO 0);
signal aux_i_address : STD_LOGIC_VECTOR (14 DOWNTO 0);
signal aux_i_read : STD_LOGIC;

signal fault_0_d_address : std_logic;
signal fault_1_d_address : std_logic;
signal fault_2_d_address : std_logic;

signal fault_0_d_byteenable : std_logic;
signal fault_1_d_byteenable : std_logic;
signal fault_2_d_byteenable : std_logic;

signal fault_0_d_read : std_logic;
signal fault_1_d_read : std_logic;
signal fault_2_d_read : std_logic;

signal fault_0_d_write : std_logic;
signal fault_1_d_write : std_logic;
signal fault_2_d_write : std_logic;

signal fault_0_d_writedata : std_logic;
signal fault_1_d_writedata : std_logic;
signal fault_2_d_writedata : std_logic;

signal fault_0_i_address : std_logic;
signal fault_1_i_address : std_logic;
signal fault_2_i_address : std_logic;

signal fault_0_i_read : std_logic;
signal fault_1_i_read : std_logic;
signal fault_2_i_read : std_logic;



component single_voter is
	generic (
		nBit : natural := 32
	);
	port (
		input0 : in std_logic_vector (nBit-1 downto 0);
		input1 : in std_logic_vector (nBit-1 downto 0);
		input2 : in std_logic_vector (nBit-1 downto 0);
		input3 : in std_logic_vector (nBit-1 downto 0);
		sel0 : in std_logic_vector (1 downto 0);
		sel1 : in std_logic_vector (1 downto 0);
		sel2 : in std_logic_vector (1 downto 0);
		correct_output : out std_logic_vector (nBit-1 downto 0);
		fault0 : out std_logic;
		fault1 : out std_logic;
		fault2 : out std_logic
	);
end component;

component single_voter_one_bit is
	port (
		input0 : in std_logic;
		input1 : in std_logic;
		input2 : in std_logic;
		input3 : in std_logic;
		sel0 : in std_logic_vector (1 downto 0);
		sel1 : in std_logic_vector (1 downto 0);
		sel2 : in std_logic_vector (1 downto 0);
		correct_output : out std_logic;
		fault0 : out std_logic;
		fault1 : out std_logic;
		fault2 : out std_logic
	);
	
end component;

begin
	voter_d_address : single_voter
	generic map(
		nBit => 15
	)
	port map(
		input0 => d_address_in_0,
		input1 => d_address_in_1,
		input2 => d_address_in_2,
		input3 => d_address_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_d_address,
		fault0 => fault_0_d_address,
		fault1 => fault_1_d_address,
		fault2 => fault_2_d_address
	);
	
	voter_d_byteenable : single_voter
	generic map(
		nBit => 4
	)
	port map(
		input0 => d_byteenable_in_0,
		input1 => d_byteenable_in_1,
		input2 => d_byteenable_in_2,
		input3 => d_byteenable_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_d_byteenable,
		fault0 => fault_0_d_byteenable,
		fault1 => fault_1_d_byteenable,
		fault2 => fault_2_d_byteenable
	);
	
	voter_d_read : single_voter_one_bit
	port map(
		input0 => d_read_in_0,
		input1 => d_read_in_1,
		input2 => d_read_in_2,
		input3 => d_read_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_d_read,
		fault0 => fault_0_d_read,
		fault1 => fault_1_d_read,
		fault2 => fault_2_d_read
	);
	
	voter_d_write : single_voter_one_bit
	port map(
		input0 => d_write_in_0,
		input1 => d_write_in_1,
		input2 => d_write_in_2,
		input3 => d_write_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_d_write,
		fault0 => fault_0_d_write,
		fault1 => fault_1_d_write,
		fault2 => fault_2_d_write
	);
	
	voter_d_writedata : single_voter
	generic map(
		nBit => 32
	)
	port map(
		input0 => d_writedata_in_0,
		input1 => d_writedata_in_1,
		input2 => d_writedata_in_2,
		input3 => d_writedata_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_d_writedata,
		fault0 => fault_0_d_writedata,
		fault1 => fault_1_d_writedata,
		fault2 => fault_2_d_writedata
	);
	
	voter_i_address : single_voter
	generic map(
		nBit => 15
	)
	port map(
		input0 => i_address_in_0,
		input1 => i_address_in_1,
		input2 => i_address_in_2,
		input3 => i_address_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_i_address,
		fault0 => fault_0_i_address,
		fault1 => fault_1_i_address,
		fault2 => fault_2_i_address
	);
	
	voter_i_read : single_voter_one_bit
	port map(
		input0 => i_read_in_0,
		input1 => i_read_in_1,
		input2 => i_read_in_2,
		input3 => i_read_in_3,
		sel0 => sel0,
		sel1 => sel1,
		sel2 => sel2,
		correct_output => aux_i_read,
		fault0 => fault_0_i_read,
		fault1 => fault_1_i_read,
		fault2 => fault_2_i_read
	);
	
	P1 : process (fault_0_d_address, fault_0_d_byteenable, fault_0_d_read, fault_0_d_write, fault_0_d_writedata, fault_0_i_address, fault_0_i_read, fault_1_d_address, fault_1_d_byteenable, fault_1_d_read, fault_1_d_write, fault_1_d_writedata, fault_1_i_address, fault_1_i_read, fault_2_d_address, fault_2_d_byteenable, fault_2_d_read, fault_2_d_write, fault_2_d_writedata, fault_2_i_address, fault_2_i_read)
	begin
		fault_0 <= fault_0_d_address or fault_0_d_byteenable or fault_0_d_read or fault_0_d_write or fault_0_d_writedata or fault_0_i_address or fault_0_i_read;
		fault_1 <= fault_1_d_address or fault_1_d_byteenable or fault_1_d_read or fault_1_d_write or fault_1_d_writedata or fault_1_i_address or fault_1_i_read;
		fault_2 <= fault_2_d_address or fault_2_d_byteenable or fault_2_d_read or fault_2_d_write or fault_2_d_writedata or fault_2_i_address or fault_2_i_read;
	end process;
	
	d_address <= aux_d_address;
    d_byteenable <= aux_d_byteenable;
    d_read <= aux_d_read;
    d_write <= aux_d_write;
    d_writedata <= aux_d_writedata;
    i_address <= aux_i_address;
    i_read <= aux_i_read;
	
end behavioral;